/**
 * 
 */
package com.module.osr.ui.stormbringer.charviewer.widgets;

import java.awt.Dimension;

import com.dalonedrau.jogl.engine.GlobalConsts;
import com.dalonedrau.jogl.engine.Render;
import com.dalonedrau.jogl.opengl.sprite.BasicSpriteObject;
import com.dalonedrau.jogl.opengl.sprite.SpriteBase;
import com.dalonedrau.jogl.opengl.sprite.SpriteImageObject;
import com.dalonedrau.jogl.opengl.sprite.SpriteImageObjectFactory;
import com.dalonedrau.jogl.opengl.ui.GuiComponentImpl;
import com.dalonedrau.jogl.opengl.ui.GuiComponentLibrary;
import com.dalonedrau.pool.PooledStringBuilder;
import com.dalonedrau.pool.StringBuilderPool;
import com.module.stormbringer.globals.Globals;
import com.rpg.base.RPGConsts;

/**
 * @author Donald
 */
public class PaperDoll extends GuiComponentImpl {
	/** the singeton instance of {@link PaperDoll}. */
	private static PaperDoll	instance;
	/**
	 * Gets the one and only instance of {@link PaperDoll}.
	 * @return {@link PaperDoll}
	 */
	public static PaperDoll getInstance() {
		if (PaperDoll.instance == null) {
			PaperDoll.instance = new PaperDoll();
		}
		return PaperDoll.instance;
	}
	/** the body layer. */
	private SpriteBase	body;
	/** the wings layer. */
	private SpriteBase	wings;
	/** the hair layer. */
	private SpriteBase	hair;
	/** the hair shadow layer. */
	private SpriteBase	hairShadow;
	/** the component's id. */
	private int			id;
	/** the size of the paper doll. */
	private Dimension	preferredSize	= new Dimension(64, 64);
	/** Hidden constructor. */
	private PaperDoll() {
		id = GuiComponentLibrary.getInstance().getNextId();
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getId() {
		return id;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public Dimension getPreferredSize() {
		if (body != null) {
			preferredSize.setSize(body.getWidth(), body.getHeight());
		}
		return preferredSize;
	}
	@Override
	public void prepareForRendering() throws Exception {
		if (wings != null) {
			Render.getInstance().registerEntity(wings);
		}
		if (body != null) {
			Render.getInstance().registerEntity(body);
		}
		if (hair != null) {
			Render.getInstance().registerEntity(hair);
		}
		if (hairShadow != null) {
			Render.getInstance().registerEntity(hairShadow);
		}
	}
	/**
	 * Sets the wings that should be displayed.
	 * @param height the height of the paper doll
	 * @throws Exception if an error occurs
	 */
	public void setWings(final int height) throws Exception {
		PooledStringBuilder sb =
			StringBuilderPool.getInstance().getStringBuilder();
		switch (height) {
		case RPGConsts.HEIGHT_00AVERAGE:
			sb.append("wings_avg");
			break;
		case RPGConsts.HEIGHT_01TALL:
			sb.append("wings_tall");
			break;
		default:
			throw new Exception("Invalid height " + height);
		}
		if (wings == null) {
			wings = new BasicSpriteObject();
			wings.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ()
					);
		}
		SpriteImageObject img =
				SpriteImageObjectFactory.getInstance().getImageByName(
						sb.toString());
		body.setImageRefId(img.getRefId());
		body.setWidth(img.getWidth());
		body.setHeight(img.getHeight());
		sb.returnToPool();
	}
	/**
	 * Sets the paper doll's body.
	 * @param doWings if true, wings are added to the doll
	 * @param attributes the list of attributes set for the paper doll.
	 * These include : [ gender, skin tone, height (average or tall), build 
	 * (light, medium, heavy), and muscle tone (average, muscular), hair style, 
	 * hair color]
	 * @throws Exception if an error occurs
	 */
	public void setBody(final boolean doWings, final int... attributes) 
	throws Exception {
		// sex_skin_height_build_muscle
		PooledStringBuilder sb =
				StringBuilderPool.getInstance().getStringBuilder();
		if (attributes[0] == RPGConsts.GENDER_MALE) {
			sb.append("m_");
		} else {
			sb.append("f_");
		}
		switch (attributes[1]) {
		case RPGConsts.SKIN_00NORSE:
			sb.append("norse_");
			break;
		case RPGConsts.SKIN_01CELT:
			sb.append("celt_");
			break;
		case RPGConsts.SKIN_02MAORI:
			sb.append("maori_");
			break;
		case RPGConsts.SKIN_03AZTEC:
			sb.append("aztec_");
			break;
		case RPGConsts.SKIN_04ZULU:
			sb.append("zulu_");
			break;
		default:
			throw new Exception("Invalid skin tone " + attributes[1]);
		}
		switch (attributes[2]) {
		case RPGConsts.HEIGHT_00AVERAGE:
			sb.append("avg_");
			break;
		case RPGConsts.HEIGHT_01TALL:
			sb.append("tall_");
			break;
		default:
			throw new Exception("Invalid height " + attributes[2]);
		}
		switch (attributes[3]) {
		case RPGConsts.BUILD_00LIGHT:
			sb.append("lt_");
			break;
		case RPGConsts.BUILD_01MEDIUM:
			sb.append("med_");
			break;
		case RPGConsts.BUILD_02HEAVY:
			sb.append("hvy_");
			break;
		default:
			throw new Exception("Invalid build " + attributes[3]);
		}
		switch (attributes[4]) {
		case RPGConsts.MUSCLE_00AVERAGE:
			sb.append("avg");
			break;
		case RPGConsts.MUSCLE_01MUSCULAR:
			sb.append("musc");
			break;
		default:
			throw new Exception("Invalid muscle " + attributes[4]);
		}
		if (body == null) {
			body = new BasicSpriteObject();
			body.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ() + GlobalConsts.CHILD_STEP
							* 0.01d
					);
		}
		SpriteImageObject img =
				SpriteImageObjectFactory.getInstance().getImageByName(
						sb.toString());
		body.setImageRefId(img.getRefId());
		body.setWidth(img.getWidth());
		body.setHeight(img.getHeight());
		System.out.println("new doll body::" + sb.toString());
		
		// HAIR SHADOW
		sb.setLength(0);
		if (attributes[5] == Globals.HAIR_STYLE00) {
			sb.append("empty_pixel");
		} else {
			if (attributes[0] == RPGConsts.GENDER_MALE) {
				sb.append("m_");
			} else {
				sb.append("f_");
			}
			switch (attributes[5]) {
			case Globals.HAIR_STYLE00:
				break;
			case Globals.HAIR_STYLE01:
					sb.append("hair1_");
				break;
			case Globals.HAIR_STYLE02:
				sb.append("hair2_");
				break;
			default:
				throw new Exception("Invalid hair style " + attributes[5]);
			}
			switch (attributes[1]) {
			case RPGConsts.SKIN_00NORSE:
				sb.append("norse_");
				break;
			case RPGConsts.SKIN_01CELT:
				sb.append("celt_");
				break;
			case RPGConsts.SKIN_02MAORI:
				sb.append("maori_");
				break;
			case RPGConsts.SKIN_03AZTEC:
				sb.append("aztec_");
				break;
			case RPGConsts.SKIN_04ZULU:
				sb.append("zulu_");
				break;
			default:
				throw new Exception("Invalid skin tone " + attributes[1]);
			}
			switch (attributes[2]) {
			case RPGConsts.HEIGHT_00AVERAGE:
				sb.append("avg");
				break;
			case RPGConsts.HEIGHT_01TALL:
				sb.append("tall");
				break;
			default:
				throw new Exception("Invalid height " + attributes[2]);
			}
		}
		if (hairShadow == null) {
			hairShadow = new BasicSpriteObject();
			hairShadow.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ() + GlobalConsts.CHILD_STEP
							* 0.02d
					);
		}
		img = SpriteImageObjectFactory.getInstance().getImageByName(
				sb.toString());
		hairShadow.setImageRefId(img.getRefId());
		hairShadow.setWidth(img.getWidth());
		hairShadow.setHeight(img.getHeight());
		System.out.println("new doll hairShadow::" + sb.toString());
		
		// HAIR
		sb.setLength(0);
		if (attributes[5] == Globals.HAIR_STYLE00) {
			sb.append("empty_pixel");
		} else {
			if (attributes[0] == RPGConsts.GENDER_MALE) {
				sb.append("m_");
			} else {
				sb.append("f_");
			}
			switch (attributes[5]) {
			case Globals.HAIR_STYLE00:
				break;
			case Globals.HAIR_STYLE01:
					sb.append("hair1_");
				break;
			case Globals.HAIR_STYLE02:
				sb.append("hair2_");
				break;
			default:
				throw new Exception("Invalid hair style " + attributes[5]);
			}
			switch (attributes[2]) {
			case RPGConsts.HEIGHT_00AVERAGE:
				sb.append("avg_");
				break;
			case RPGConsts.HEIGHT_01TALL:
				sb.append("tall_");
				break;
			default:
				throw new Exception("Invalid height " + attributes[2]);
			}
			switch (attributes[6]) {
			case Globals.HAIR_COLOR_BLONDE_GOLD:
				sb.append("blondegold");
				break;
			case Globals.HAIR_COLOR_BLONDE_LT:
				sb.append("blondelt");
				break;
			case Globals.HAIR_COLOR_RED:
				sb.append("red");
				break;
			case Globals.HAIR_COLOR_BRUNETTE:
				sb.append("brunette");
				break;
			case Globals.HAIR_COLOR_BLACK:
				sb.append("black");
				break;
			case Globals.HAIR_COLOR_GREY:
				sb.append("grey");
				break;
			default:
				throw new Exception("Invalid hair color " + attributes[6]);
			}
		}
		if (hair == null) {
			hair = new BasicSpriteObject();
			hair.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ() + GlobalConsts.CHILD_STEP
							* 0.02d
					);
		}
		img = SpriteImageObjectFactory.getInstance().getImageByName(
				sb.toString());
		hair.setImageRefId(img.getRefId());
		hair.setWidth(img.getWidth());
		hair.setHeight(img.getHeight());
		System.out.println("new doll hair::" + sb.toString());
		
		// WINGS
		sb.setLength(0);
		if (doWings) {
			switch (attributes[2]) {
			case RPGConsts.HEIGHT_00AVERAGE:
				sb.append("wings_avg");
				break;
			case RPGConsts.HEIGHT_01TALL:
				sb.append("wings_tall");
				break;
			default:
				throw new Exception("Invalid height " + attributes[2]);
			}
		} else {
			sb.append("empty_pixel");
		}
		if (wings == null) {
			wings = new BasicSpriteObject();
			wings.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ()
					);
		}
		img = SpriteImageObjectFactory.getInstance().getImageByName(
						sb.toString());
		wings.setImageRefId(img.getRefId());
		wings.setWidth(img.getWidth());
		wings.setHeight(img.getHeight());
		System.out.println("new doll wings::" + sb.toString());
		sb.returnToPool();
	}
	@Override
	public void setPosition(final double x, final double y, final double z) {
		super.setPosition(x, y, z);
		if (wings != null) {
			wings.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ()
					);
		}
		if (body != null) {
			body.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ() + GlobalConsts.CHILD_STEP
							* 0.01d
					);
		}
		if (hair != null) {
			hair.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ() + GlobalConsts.CHILD_STEP
							* 0.02d
					);
		}
		if (hairShadow != null) {
			hairShadow.setPosition(
					super.getPosition().getX(),
					super.getPosition().getY(),
					super.getPosition().getZ() + GlobalConsts.CHILD_STEP
							* 0.02d
					);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setPositionExcludingBorders(double x, double y, double z) {
		// TODO Auto-generated method stub
		super.setPositionExcludingBorders(x, y, z);
		if (wings != null) {
			wings.setPosition(x, y, z);
		}
		if (body != null) {
			body.setPosition(x, y, z);
		}
		if (hair != null) {
			hair.setPosition(x, y, z);
		}
		if (hairShadow != null) {
			hairShadow.setPosition(x, y, z);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setPreferredSize(int width, int height) {}
}
